#!/usr/bin/env python
# -*- coding:utf-8 -*-

# For Python3


# from __future__ import print_function
import random
import struct

import paho.mqtt.client as mqtt
import json
import time

# CONNECT 方式：
# client_id:     DEV_ID
# username:  PRO_ID
# password:   AUTHINFO(鉴权信息)
# 可以连接上设备云，CONNECT 和 CONNACK握手成功
# PRO_ID:项目ID
# API_KEY:设备API_KEY
# DEV_ID:设备ID
# temperature:已创建的一个数据流
#
# 我订阅的主题是PRO_ID/API_KEY/DEV_ID/temperature
# 我发布的主题是DEV_ID/temperature

# MQTT对应TCP连接服务器地址及端口
# OneNET线上 host：183.230.40.39  port: 6002

# 线上设备信息


DEV_ID = "xxxx"
PRO_ID = "xxxx"
AUTH_INFO = "xxxx"
API_KEY = "xxxx"

HOST = '183.230.40.39'
PORT = 6002


TYPE_JSON = b'\x01'

PUB_FLAG = False

body = {"datastreams": [{"id":"temperature", "datapoints":[{"at": "2016-08-15T14:47:00", "value": 78}]}]}


def ts_print(*args):
    t = time.strftime("[%Y-%m-%d %H:%M:%S]:")
    print(t, *args)


def build_payload(d_type, data):
    d_len = bytes.fromhex(hex(len(data))[2:].zfill(4))
    payload = d_type + d_len
    if isinstance(data, str):
        payload += data.encode('utf-8')
    elif isinstance(data, bytes):
        payload += data
    ts_print(payload)
    # print(payload.hex())
    return payload


def type3_payload(data):
    packet = b'\x03'

    data = json.dumps(data)
    len_data = bytes.fromhex(hex(len(data))[2:].zfill(4))
    data = data.encode()
    packet += len_data + data
    return packet


def type2_payload(ds_id, bin_data):
    packet = b'\x02'
    t = time.strftime("%Y-%m-%d %H:%M:%S")
    ds_json = {'ds_id': ds_id, 'at': t}
    ds_data = json.dumps(ds_json)
    len_data = bytes.fromhex(hex(len(ds_data))[2:].zfill(4))
    data = ds_data.encode()
    packet += len_data + data

    len_data = bytes.fromhex(hex(len(bin_data))[2:].zfill(8))
    packet += len_data + bin_data
    return packet


def type4_payload(data):
    packet = b'\x04'
    data = json.dumps(data)
    len_data = bytes.fromhex(hex(len(data))[2:].zfill(4))
    data = data.encode()
    packet += len_data + data
    return packet


def type5_payload(data):
    packet = b'\x05'
    len_data = bytes.fromhex(hex(len(data))[2:].zfill(4))
    data = data.encode()
    packet += len_data + data
    return packet


def type6_payload(data):
    packet = bytes([int(0b10000110)])
    t = time.strftime("%Y%m%d%H%M%S")[2:]
    t = bytes.fromhex(t)
    packet += t

    len_data = bytes.fromhex(hex(len(data))[2:].zfill(4))
    data = data.encode()
    packet += len_data + data
    return packet


def type7_payload(data):
    packet = bytes([int(0b10000111)])
    t = time.strftime("%Y%m%d%H%M%S")[2:]
    t = bytes.fromhex(t)
    packet += t

    ds_id = b'\x00\x01'
    ds_no = b'\x00\x01'

    data = struct.pack('f', data)
    packet += ds_id + ds_no + data
    return packet


def on_connect(client, userdata, flags, rc):
    ts_print("<<<<CONNACK")
    ts_print("connected with result code " + mqtt.connack_string(rc))

    client.subscribe('xxx')
    client.subscribe('will')


# on_message() 接收OneNET命令
# msg.topic: $creq/a18a4aa0-8681-5341-997c-80147d13a753
# str(msg.payload): b'123456789'
def on_message(client, userdata, msg):
    ts_print('on_message')
    ts_print(msg.topic+" ", msg.payload)

    if msg.topic.startswith('$creq/'):
        cmd_uuid = msg.topic[6:]
        topic_resp = '$crsp/' + cmd_uuid
        client.publish(topic_resp, msg.payload)
        ts_print('Publish >>> ', topic_resp, msg.payload)


def on_publish(client, userdata, mid):
    ts_print("<<<<PUBACK")
    ts_print("mid: " + str(mid))


def on_subscribe(client, obj, mid, granted_qos):
    print("Subscribed: mid: " + str(mid) + "  qos:" + str(granted_qos))


def on_disconnect(client):
    ts_print('DISCONNECTED')


if __name__ == '__main__':

    client = mqtt.Client(client_id=DEV_ID, protocol=mqtt.MQTTv311)
    client.on_connect = on_connect
    client.on_publish = on_publish
    client.on_message = on_message
    client.on_subscribe = on_subscribe

    # client.will_set('xxx', payload=b"I'm leaving", qos=0)

    client.username_pw_set(username=PRO_ID, password=AUTH_INFO)
    client.connect(host=HOST, port=PORT, keepalive=10)

    # client.loop_forever()
    client.loop_start()

    while True:
        # time.sleep(20)
        # t = time.strftime("%Y-%m-%dT%H:%M:%S")
        type1_data = {"datastreams": [{"id": "type1", "datapoints": [{"at": "2016-08-15T14:47:00", "value": random.randint(1, 10000)}]}]}
        # type1_data = {"datastreams": [{"id": "type1", "datapoints": [{"at": time.strftime("%Y-%m-%d %H:%M:%S"), "value": '我的'}]}]}
        json_body = json.dumps(type1_data, ensure_ascii=False)
        packet = build_payload(TYPE_JSON, json_body)
        client.publish("$dp", packet, qos=1)
        time.sleep(8)
        type3_data = {"type3": 1}
        packet = type3_payload(type3_data)
        print('type3_payload', packet)
        client.publish("$dp", packet)

        time.sleep(8)
        # type2_data = 'abcdefgffffffffffffffffffffffffffffffffffffff'.encode()
        type2_data = bytes.fromhex('005841313030303032343145363032303134333833303042')
        print(len(type2_data))
        packet = type2_payload('type2', bin_data=type2_data)
        print('type2_payload', packet)
        client.publish("$dp", packet)
        # time.sleep(8)

        time.sleep(8)
        type7_data = 1.1
        packet = type7_payload(type7_data)
        print('type7_payload', packet)
        client.publish("$dp", packet)

        time.sleep(5)
        type6_data = ',;type6,%d' % random.randint(1,100)
        packet = type6_payload(type6_data)
        print('type6_payload', packet)
        client.publish("$dp", packet)

        time.sleep(5)
        type5_data = ',;type5,%d' % random.randint(1,100)
        packet = type5_payload(type5_data)
        print('type5_payload', packet)
        client.publish("$dp", packet)

        time.sleep(8)
        t = time.strftime("%Y-%m-%d %H:%M:%S")
        type4_data = {'type4':{t: random.randint(1,100)}}
        packet = type4_payload(type4_data)
        print('type2_payload', packet)
        client.publish("$dp", packet)

    # client.loop_stop()

